package com.bjpowernode.boss.mvc.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bjpowernode.boss.client.RedisClient;
import com.bjpowernode.boss.constant.KeyConstant;
import com.bjpowernode.boss.enums.RespInfo;
import com.bjpowernode.boss.exception.PowerException;
import com.bjpowernode.boss.mvc.models.dto.LoginResultDto;
import com.bjpowernode.boss.mvc.models.dto.MenusDto;
import com.bjpowernode.boss.mvc.models.query.LoginQuery;
import com.bjpowernode.boss.mvc.service.OperatorService;
import com.bjpowernode.boss.persist.domain.PmsOperator;
import com.bjpowernode.boss.persist.mapper.PmsMenuMapper;
import com.bjpowernode.boss.persist.mapper.PmsOperatorMapper;
import com.bjpowernode.boss.utils.JwtUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class OperatorServiceImpl implements OperatorService {

    @Resource
    private RedisClient redisClient;

    @Resource
    private PmsOperatorMapper operatorMapper;

    @Resource
    private PmsMenuMapper menuMapper;

    private Object lock = new Object();

    @Override
    public LoginResultDto login(LoginQuery loginQuery) {

        PmsOperator operator = operatorMapper.selectOne(new QueryWrapper<PmsOperator>()
                .eq("login_name", loginQuery.getLoginName()));


        if (operator == null) {
            throw new PowerException(RespInfo.LOGIN_INFO_ERROR);
        }

        String loginPwd = DigestUtil.md5Hex(loginQuery.getLoginPwd() + operator.getSalt());
        if (!loginPwd.equals(operator.getLoginPwd())) {
            throw new PowerException(RespInfo.LOGIN_INFO_ERROR);
        }

        String jwt = JwtUtil.createJWT("operatorId:" + operator.getId());

        Map<String, String> map = new HashMap<>();
        map.put("id", String.valueOf(operator.getId()));
        map.put("jwt", jwt);
        map.put("loginTime", DateUtil.format(new Date(), "yyyyMMddHHmmss"));

        String tokenKey = KeyConstant.OPERATOR_TOKEN + operator.getId();
        boolean save = redisClient.setHashAll(tokenKey, map, 20, TimeUnit.MINUTES);
        if (!save) {
            throw new PowerException(RespInfo.INFO_SAVE_ERROR);
        }
        return LoginResultDto
                .builder()
                .id(operator.getId())
                .showName(operator.getShowName())
                .jwt(jwt)
                .build();
    }

    @Override
    public List<MenusDto> getMenus(Integer operatorId) {
        String key = KeyConstant.OPERATOR_MENUS + operatorId;
        try {
            synchronized (lock) {
                String value = redisClient.getValue(key);
                if (StrUtil.isNotBlank(value)){
                    return JSONUtil.toList(value, MenusDto.class);
                } else {
                    List<MenusDto> menusDtoList = menuMapper.selectByOperatorId(operatorId);
                    redisClient.setValue(key, JSONUtil.toJsonStr(menusDtoList));
                    return menusDtoList;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return menuMapper.selectByOperatorId(operatorId);
        }
    }

    @Override
    public void logout(Integer operatorId) {

        String key = KeyConstant.OPERATOR_MENUS + operatorId;

        if (redisClient.exists(key) && redisClient.deleteKey(key)){
            return;
        }
        throw new PowerException(RespInfo.OPERATOR_TOKEN_NOT_EXIST);

    }






}
